/**
 * @date 2006-9-11
 */

package org.nanhill.commons.model.pagination;

/**
 * Classic three part pagination.
 * 
 * @author alin [xalinx at gmail dot com]
 * @date 2006-9-11
 */
public class ThreePartNumberPagination<E> extends Pagination<E> implements
		Numberable {
	private static final int DEFAULT_START_PAGES = 2;

	private static final int DEFAULT_END_PAGES = 2;

	private static final int DEFAULT_BEFORE_PAGES = 2;

	private static final int DEFAULT_AFTER_PAGES = 2;

	/**
	 * Start pages.
	 */
	protected int startPageCount = DEFAULT_START_PAGES;

	/**
	 * End pages.
	 */
	protected int endPageCount = DEFAULT_END_PAGES;

	/**
	 * Pages before now page.
	 */
	protected int beforePageCount = DEFAULT_BEFORE_PAGES;

	/**
	 * Pages after now page.
	 */
	protected int afterPageCount = DEFAULT_AFTER_PAGES;

	public int[] getNumbers() {
		int[] numbers;
		int pageCount = this.getPageCount();
		int maxPageCount = this.getMaxPageCount();
		if (pageCount <= maxPageCount) {
			numbers = new int[pageCount];
			for (int i = 0; i < pageCount; i++) {
				numbers[i] = i + 1;
			}
		} else {
			// 2 indicate two splitors(use 0 as splitor)
			maxPageCount += 2;
			// build start part
			numbers = new int[maxPageCount];
			int fi = 0;
			for (; fi < startPageCount; fi++) {
				numbers[fi] = fi + 1;
			}
			// build center part
			int si = fi;
			int pid = pageId - beforePageCount;
			if (pid - 1 > fi) {
				si++;
			} else {
				si = pid - 1;
			}
			int n = si + beforePageCount + afterPageCount + 1;
			for (; si < n; si++, pid++) {
				if (si >= 0)
					numbers[si] = pid;
			}
			// build end part
			int ti = si > fi ? si : fi;
			int tpid = pageCount - endPageCount + 1;
			if (tpid > pid) {
				ti++;
			} else {
				ti -= pid - tpid;
			}
			n = ti + endPageCount;
			for (; ti < n; ti++, tpid++) {
				numbers[ti] = tpid;
			}
			if (ti < maxPageCount) {
				int[] temp = new int[ti];
				System.arraycopy(numbers, 0, temp, 0, ti);
				numbers = temp;
			}
		}
		return numbers;
	}

	public int getAfterPageCount() {
		return afterPageCount;
	}

	public void setAfterPageCount(int afterPageCount) {
		this.afterPageCount = afterPageCount;
	}

	public int getBeforePageCount() {
		return beforePageCount;
	}

	public void setBeforePageCount(int beforePageCount) {
		this.beforePageCount = beforePageCount;
	}

	public int getEndPageCount() {
		return endPageCount;
	}

	public void setEndPageCount(int endPageCount) {
		this.endPageCount = endPageCount;
	}

	public int getStartPageCount() {
		return startPageCount;
	}

	public void setStartPageCount(int startPageCount) {
		this.startPageCount = startPageCount;
	}

	protected int getMaxPageCount() {
		// 1 indicate this page
		return startPageCount + endPageCount + beforePageCount + afterPageCount
				+ 1;
	}

}
